<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace Hyperfx\ServiceGovernanceNacos\NodeSelector;

use Hyperf\Grpc\StatusCode;
use Hyperf\GrpcClient\Exception\GrpcClientException;
use Hyperf\LoadBalancer\AbstractLoadBalancer;
use Hyperf\LoadBalancer\LoadBalancerManager;
use Hyperf\LoadBalancer\Node;

class NodeSelector
{
    /**
     * @var array
     */
    public $services;

    private string $algorithm = 'random';

    public function register(string $service, array $nodes): void
    {
        $loadBalancerManager = new LoadBalancerManager();
        $loadBalancer = $loadBalancerManager->get($this->algorithm);
        $this->services[$service] = make($loadBalancer, [$nodes]);
    }

    public function has(string $service): bool {
        return isset($this->services[$service]);
    }

    public function refresh(string $service, array $nodes): void
    {
        if (empty($nodes)) {
            return;
        }
        /* @var $loadBalancer AbstractLoadBalancer */
        $loadBalancer = $this->services[$service];
        $loadBalancer->setNodes($nodes);
    }

    public function select(string $service, array ...$parameters): Node
    {
        if (!isset($this->services[$service])) {
            throw new GrpcClientException(sprintf('此服务[%s]尚未注册,请检查配置文件 %s', $service, posix_getpid()), StatusCode::INTERNAL);
        }
        /* @var $loadBalancer AbstractLoadBalancer */
        $loadBalancer = $this->services[$service];
        return $loadBalancer->select($parameters);
    }
}
